/**
 *	数据库表格管理
 *	开发者：雨中磐石
 *	地址：www.rockoa.com
 *	日期：2023-07-19
 */

package com.framework.Table;

import com.framerock.baselib.CLog;
import com.framerock.db.DB;
import com.framerock.db.DBConn;
import com.framerock.baselib.Jiami;
import com.framerock.baselib.Rock;
import com.framework.ACore.Model;
import com.framework.ACore.ModuleFields;
import com.framework.ACore.ModuleInfo;
import com.framework.ACore.ModuleTodo;
import com.framework.ACore.ModuleWhere;
import com.framework.Flow.FlowGroup;
import com.rock.xinhujava.RainRock;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Map;

public class Table {

    protected DBConn nDb    = null;

    protected void initTable() { }
    protected void firstInsert() { }

    protected String tablename     = ""; //表名不带前缀
    protected String tablenameal   = ""; //完整表名
    protected String tablenamesm   = ""; //表名说明

    protected Map<String, String> flowsetMap = null; //是否添加模块信息

    public Table(){

    }
    public Table(DBConn dbs){
        setDb(dbs);
    }

    public void setDb(DBConn dbs)
    {
        if(this.nDb != null)return;
        this.nDb = dbs;
        initTable();
    }

    /*
    *   获取表格创建
     */
    public static Table get(DBConn dbs, String tab, String sm)
    {
        Table obj = new Table(dbs);
        obj.tablename   = tab;
        obj.tablenameal = DB.chuliPerfix(tab);
        obj.tablenamesm = sm;
        return obj;
    }

    /**
     * 获取要创建的表格
     * */
    public static Table get(String num, String group)
    {
        if(Rock.isEmpt(group))group = FlowGroup.get(num);
        Table obj = getObjTable(num,group, "framework");
        if(obj == null && !Rock.isEmpt(RainRock.MYFOLDER)) {
            obj = getObjTable(num,group, RainRock.MYFOLDER);
        }
        return obj;
    }
    private static Table getObjTable(String num, String group, String folder)
    {
        String classna = "com."+folder+".Module";
        if(!Rock.isEmpt(group))classna += "."+group+"";
        classna += "."+num+".Table"+num+"";
        try {
            Class<?> clazz = Class.forName(classna);
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            Table obj = (Table)constructor.newInstance();
            return obj;
        } catch (Exception e) {
            CLog.error("not found "+classna+"");
        }
        return null;
    }


    //表格字段数组
    protected ArrayList<Map<String, String>> fieldslist = null,wherelist = null,ftodolist=null,fmenulist=null;

    /**
     * 设置表格信息
     * @param table 对应表不用前缀
     * @param name 名称
     * */
    public void setInfo(String table, String name)
    {
        this.tablename   = table;
        this.tablenamesm = name;
    }

    //加字段
    public void addfields(String fields, String type, String dev, String sm, String[] params)
    {
        if(Rock.isEmpt(tablenameal))tablenameal = DB.chuliPerfix(tablename);
        Map<String, String> da = Rock.getMap(params);
        da.put("fields", fields);
        da.put("type", type);
        da.put("dev", dev);
        da.put("sm", sm);
        if(fieldslist ==null)fieldslist = Rock.getMapList();
        fieldslist.add(da);
    }
    public void addfields(String fields, String type, String dev, String sm)
    {
        addfields(fields, type, dev,sm,new String[]{});
    }

    /**
     * 设置模块信息
     * */
    public void setModuleInfo(ModuleInfo info)
    {
        this.flowsetMap = info.getMap();
    }

    /**
     * 添加模块字段
     * */
    public void addModuleFields(ModuleFields fields)
    {
        if(Rock.isEmpt(tablenameal))tablenameal = DB.chuliPerfix(tablename);
        if(fieldslist ==null)fieldslist = Rock.getMapList();
        fieldslist.add(fields.getMap());
    }

    /**
     * 获取表名，带前缀的
     * */
    public String getTablename()
    {
        return this.tablenameal;
    }

    /**
     * 添加默认的模块条件
     * @param name 条件名称
     * @param num 条件编号
     * @param where 条件内容如1=1，aid={aid}
     * @param params 其他字段，如wtype=1
     * */
    public void addWhere(String name, String num, String where, String params)
    {
        Map<String, String> da = Rock.getMap(params);
        da.put("name", name);
        da.put("num", num);
        da.put("where", Jiami.base64encode(where));
        if(wherelist ==null)wherelist = Rock.getMapList();
        wherelist.add(da);
    }

    /**
     * 添加默认的模块条件
     * @param name 条件名称
     * @param num 条件编号
     * @param where 条件内容如1=1，aid={aid}
     * */
    public void addWhere(String name, String num, String where)
    {
        addWhere(name, num, where, "");
    }

    /**
     * 添加默认的模块条件
     * */
    public void addWhere(ModuleWhere modulewhere)
    {
        if(wherelist ==null)wherelist = Rock.getMapList();
        Map<String, String> da = modulewhere.getMap();
        if(da != null)wherelist.add(da);
    }

    /**
     * 添加默认的单据通知设置
     * */
    public void addFlowTodo(String num, String[] params)
    {
        Map<String, String> da = Rock.getMap(params);
        da.put("num", num);
        if(ftodolist ==null)ftodolist = Rock.getMapList();
        ftodolist.add(da);
    }

    /**
     * 添加默认的单据通知设置
     * */
    public void addFlowTodo(ModuleTodo moduletodo)
    {
        Map<String, String> da = moduletodo.getMap();
        if(ftodolist ==null)ftodolist = Rock.getMapList();
        ftodolist.add(da);
    }

    /**
     * 添加默认的单据菜单菜单
     * */
    public void addFlowMenu(String num, String[] params)
    {
        Map<String, String> da = Rock.getMap(params);
        da.put("num", num);
        String where = Rock.getMapString(da, "where");
        if(!Rock.isEmpt(where))da.put("where", Jiami.base64encode(where));
        if(fmenulist ==null)fmenulist = Rock.getMapList();
        fmenulist.add(da);
    }

    /**
     * 创建表格
     * */
    public String createTable(String allTab[])
    {
        if(Rock.inArray(allTab, this.tablenameal))return "tableEXISTS";

        String idkey  = "`id` int(11) NOT NULL AUTO_INCREMENT";
        String okey	  = "PRIMARY KEY (`id`)";
        String sql    = "",str = "",type,fields,bstr="";
        Map<String, String> da;
        for(int i=0;i<fieldslist.size();i++){
            da      = fieldslist.get(i);
            type    = da.get("type");
            fields  = da.get("fields");
            if(fields.equals("id") || fields.indexOf("temp_")==0)continue;
            if(Rock.contain(type, "KEY")){
                okey+=","+type+" `"+fields+"` ("+da.get("dev")+")";
            }else {
                str += "," + getFieldstr(da);
            }
        }
        sql = "CREATE TABLE IF NOT EXISTS `"+this.tablenameal+"` ("+idkey+" "+str+","+okey+") ENGINE=InnoDB DEFAULT CHARSET="+DB.CHARSET+" COMMENT='"+this.tablenamesm+"';";
        Boolean bo = this.nDb.Query(sql);

        if(bo){
            bstr = "createok";
            this.firstInsert();
        }
        return bstr;
    }

    /**
     * 更新数据库表格
     * */
    public String updateTable(String allTab[])
    {
        if(!Rock.inArray(allTab, this.tablenameal))return this.createTable(allTab);//不存在就创建

        ArrayList<Map<String, String>> farr = this.nDb.getColumns(this.tablenameal);
        if(farr==null)return "";
        String bstr = "";
        Map<String, String> da, fobj = Rock.getMap();
        for(int i=0;i<farr.size();i++){
            da      = farr.get(i);
            fobj.put(da.get("fields"), this.getFieldstr(da));
        }
        String sql    = "",str,ostr,type,fields;
        for(int i=0;i<fieldslist.size();i++){
            da      = fieldslist.get(i);
            type    = da.get("type");
            fields  = da.get("fields");
            if(fields.equals("id") || fields.indexOf("temp_")==0)continue;
            if(!Rock.contain(type, "KEY")){
                ostr= Rock.getMapString(fobj, fields);
                str = this.getFieldstr(da);
                if(Rock.isEmpt(ostr)) {
                    sql+=",ADD "+str+"";
                }else{
                    if(!Rock.equals(str, ostr)){
                        sql+=",MODIFY "+str+"";
                    }
                }
            }
        }
        if(!Rock.isEmpt(sql)) {
            sql = "ALTER TABLE "+DB.chuliTable(this.tablenameal)+" "+sql.substring(1)+"";
            this.nDb.Query(sql);
            bstr = sql;
        }
        this.firstInsert();
        return bstr;
    }

    /**
     * 添加主键
     * */
    public void addIndex(String key)
    {
        String sql = "CREATE INDEX "+key+" on "+DB.chuliTable(this.tablenameal)+" ("+key+")";
        this.nDb.Query(sql);
    }

    /**
     *	字段信息
     */
    public String getFieldstr(Map<String, String> rs)
    {
        String str = "`"+rs.get("fields")+"` "+rs.get("type")+"";
        String dev = rs.get("dev"),sm = rs.get("sm");
        if(dev==null || dev.equals("null")){
            str+=" DEFAULT NULL";
        }else{
            str+=" DEFAULT '"+dev+"'";
        }
        if(!Rock.isEmpt(sm))str+=" COMMENT '"+sm+"'";
        return str;
    }

    /**
     * 创建模块和字段信息
     * */
    public String createMode()
    {
        if(this.flowsetMap==null)return "";

        Map<String, String> setda = Rock.getMap();
        setda.put("table", this.tablename);
        setda.put("num", this.tablename);
        setda.put("name", this.tablenamesm);
        for(Map.Entry<String,String> entry:this.flowsetMap.entrySet()){
            setda.put(entry.getKey(),entry.getValue());
        }
        String num = Rock.getMapString(setda, "num");
        Model mobjv = Model.get(this.nDb, "flowset");
        String swhere = "`num`='"+num+"'",modeid="0";
        Map<String, String> moders = mobjv.getOne(swhere);

        if(moders==null){
            modeid = ""+mobjv.insert(setda);
        }else{
            modeid = Rock.getMapString(moders, "id");
            mobjv.update(setda, swhere);
        }

        String type,fields,sm,where,fieldstype,dev,bstr="",ustr="",svt,data,lens;
        int sort = 0,i,j;
        Map<String, String> da,nda;
        Model mfobj  = Model.get(this.nDb, "flowelement");

        String farr[] = {"isbt","islb","dev","attr","ftype","islu","iszs","isss","isonly","isdr","ispx","sort","lens","isalign","iseditlx","placeholder","zdsm","data","gongshi"};

        for(i=0;i<fieldslist.size();i++) {
            da      = fieldslist.get(i);
            type    = da.get("type");
            fields  = da.get("fields");
            sm      = da.get("sm");
            dev     = da.get("dev");
            if(dev==null || dev.equals("null"))dev = "";
            if(Rock.isEmpt(sm))continue;
            if(Rock.getMapString(da, "notelement").equals("1"))continue;//不加表单元素

            sort++;
            where   = "`modeid`="+modeid+" and `fields`='"+fields+"'";
            if(Rock.contain(type, "KEY"))continue;

            nda = Rock.getMap();
            fieldstype   = Rock.getMapString(da, "fieldstype", "text");
            lens         = "0";
            data         = "";
            String arr[] = sm.split("@");
            nda.put("modeid", modeid);
            nda.put("fields", fields);
            nda.put("dev", dev);
            nda.put("sort", ""+sort+"");
            nda.put("name", arr[0]);
            if(fields.equals("id")){
                nda.put("islu", "0");
                nda.put("ispx", "1");
                nda.put("isss", "1");
            }

            if(arr.length>1)data = arr[1];
            nda.put("data", data);
            if(arr.length>2)nda.put("placeholder", arr[2]);

            if(fieldstype.equals("text")) {
                if (type.equals("tinyint(1)")) {
                    if (Rock.isEmpt(data)) {
                        fieldstype = "checkbox";
                    } else {
                        fieldstype = "select";
                    }
                } else if (type.equals("datetime") || type.equals("date")) {
                    fieldstype = type;
                } else if (Rock.contain(type, "int(")) {
                    fieldstype = "number";
                    lens = "0";
                } else {
                    if (Rock.contain(type, "varchar(")) {
                        lens = type.replace("varchar(", "");
                        lens = lens.replace(")", "");
                    }
                    if (!Rock.isEmpt(data))fieldstype = "select";
                }
            }

            nda.put("fieldstype", fieldstype);
            nda.put("dbtype", type);
            nda.put("lens", lens);

            for(j=0;j<farr.length;j++) {
                svt = Rock.getMapString(da, farr[j]);
                if(!Rock.isEmpt(svt))nda.put(farr[j], svt);
            }
            String str = da.get("devval");
            if(!Rock.isEmpt(str))nda.put("dev", str);

            if(mfobj.getCount(where)==0) {
                mfobj.insertbo(nda);
                if (bstr.length() > 0) bstr += ",";
                bstr += "" + fields + "";
            }else{
                mfobj.update(nda, where);
                if (ustr.length() > 0) ustr += ",";
                ustr += "" + fields + "";
            }
        }

        String name;
        int wci = 0,tci = 0,mci=0;
        Model wfobj  = Model.get(this.nDb, "flowwhere");
        if(wherelist != null)for(i=0;i<wherelist.size();i++) {
            wci++;
            da      = wherelist.get(i);
            da.put("modeid", modeid);
            da.put("sort", ""+i);
            num     = da.get("num");
            name    = da.get("name");
            where   = "`modeid`="+modeid+" and `num`='"+num+"'";

            if(wfobj.getCount(where)==0) {
                wfobj.insertbo(da);
            }else{
                wfobj.update(da, where);
            }
        }

        Model tfobj  = Model.get(this.nDb, "flowtodo");
        if(ftodolist != null)for(i=0;i<ftodolist.size();i++) {
            tci++;
            da      = ftodolist.get(i);
            da.put("modeid", modeid);
            num     = da.get("num");
            where   = "`modeid`="+modeid+" and `num`='"+num+"' and `cid`=0";

            if(tfobj.getCount(where)==0) {
                tfobj.insertbo(da);
            }else{
                tfobj.update(da, where);
            }
        }

        Model fmobj  = Model.get(this.nDb, "flowmenu");
        if(fmenulist != null)for(i=0;i<fmenulist.size();i++) {
            mci++;
            da      = fmenulist.get(i);
            da.put("modeid", modeid);
            num     = da.get("num");
            where   = "`modeid`="+modeid+" and `num`='"+num+"' and `cid`=0";

            if(fmobj.getCount(where)==0) {
                fmobj.insertbo(da);
            }else{
                fmobj.update(da, where);
            }
        }


        wherelist = null;
        ftodolist = null;
        fmenulist = null;
        return ""+num+":add("+bstr+"),update("+ustr+"),where("+wci+"),ftodo("+tci+"),fmenu("+mci+")";
    }
}
